make getform work (without DirichletBCs) for DOLFINx#200
Conversation
Co-authored-by: Copilot <copilot@github.com>
| - `bcnew`, a list of :class:`firedrake.DirichletBC` or :class:`EquationBC` | ||
| objects to be posed on the stages | ||
| """ | ||
| backend_cls = get_backend(backend) |
There was a problem hiding this comment.
Should we try to consistenty set a backend variable name throught different files? In base_time_stepper we repeatedly call self._backend, but here we define backend_cls.
There was a problem hiding this comment.
I would say it depends on wether we are within a class (that takes backend at construction) or a function that takes backend as an argument.
I think using the string for backend to stand-alone functions (and then fetching the backend class), is a good option, and for classes set a self._backend at construction. However, open to alternatives.
| assert V == backend_cls.get_function_space(u0) | ||
|
|
||
| c = vecconst(butch.c) | ||
| c = vecconst(butch.c, backend=backend) |
There was a problem hiding this comment.
Should we implement backend_cls.vecconst? The name of this function could also be improved, especially because this function returns ufl.zero for numeric values equal to zero.
There was a problem hiding this comment.
The reason I did it in the given way, with backend as input, is that the UFL operations in vecconst is the same for both implementations, i.e.
import numpy as np
from .backend import get_backend, Backend
import ufl
def MeshConstant(msh, backend: str = "firedrake"):
mc_backend = get_backend(backend)
return mc_backend.MeshConstant(msh)
def ConstantOrZero(
x: float | complex,
MC: Backend.MeshConstant | None = None,
backend: str = "firedrake",
) -> ufl.core.expr.Expr:
backend_impl = get_backend(backend)
const = backend_impl.get_mesh_constant(MC)
return ufl.zero() if abs(complex(x)) < 1.0e-10 else const(x)
vecconst = np.vectorize(ConstantOrZero)If aimed to reduce the amount of duplicate code across the modules.
If you think another option is better I am open for it (but it would be nice to not have to have to versions of ufl.zero() if abs(complex(x)) < 1.0e-10 else const(x) as I feel they can easily divergece (especially the floating point tolerance).
|
I think this PR should not apply changes that are merely (ruff) formatting. This makes it a bit harder to review. |
| Function = firedrake.Function | ||
|
|
||
| DirichletBC = firedrake.DirichletBC | ||
|
|
||
| norm = firedrake.norm | ||
|
|
||
| assemble = firedrake.assemble | ||
|
|
||
| replace = firedrake.replace | ||
|
|
||
| derivative = firedrake.derivative | ||
| TestFunction = firedrake.TestFunction | ||
| TrialFunction = firedrake.TrialFunction |
There was a problem hiding this comment.
Do we need to define varibales? Can these not be just imports?
There was a problem hiding this comment.
They can, I added them here for clarity in case we ever need to do more than just reference them directly. I'm happy to adapt to whatever coding style you would like.
| return type(self)( | ||
| V, | ||
| g, | ||
| sub_domain, | ||
| self.bounds, | ||
| self.solver_parameters, | ||
| backend=self._backend_name, | ||
| ) |
Co-authored-by: Pablo Brubeck <brubeck@protonmail.com>
| F_remainder = expand_time_derivatives( | ||
| split_form.remainder, t=t, timedep_coeffs=() | ||
| ) |
| onscale_factor=1.2, | ||
| safety_factor=0.9, | ||
| gamma0_params=None, | ||
| backend_cls: str = "firedrake", |
| assert butcher_tableau.btilde is not None | ||
| super(AdaptiveTimeStepper, self).__init__( | ||
| F, | ||
| butcher_tableau, | ||
| t, | ||
| dt, | ||
| u0, | ||
| bcs=bcs, | ||
| appctx=appctx, | ||
| solver_parameters=solver_parameters, | ||
| bc_type=bc_type, | ||
| splitting=splitting, | ||
| nullspace=nullspace, | ||
| **kwargs, | ||
| ) |
| @@ -1,3 +1,3 @@ | |||
| # formulate RK methods to solve for stage values rather than the stage derivatives. | |||
| import numpy | |||
| from firedrake import TestFunction | |||
| @@ -2,6 +2,7 @@ | |||
| from ufl import BaseForm, Form, FormSum | |||
There was a problem hiding this comment.
Drop all changes here. The correct fix is to expose LabelledForm.arguments()
There was a problem hiding this comment.
If you fix that I'll revert this. Currently this is needed to get any work done on the DOLFINx end of things.
Co-authored-by: Jørgen Schartum Dokken <dokken92@gmail.com>
Co-authored-by: Jørgen Schartum Dokken <dokken92@gmail.com>
| self.sample_values = [ | ||
| sum(ks[j] * vander[j, i] for j in range(len(ks))) | ||
| for i in range(num_samples) | ||
| ] |
There was a problem hiding this comment.
| self.sample_values = [ | |
| sum(ks[j] * vander[j, i] for j in range(len(ks))) | |
| for i in range(num_samples) | |
| ] | |
| self.sample_values = [sum(ks[j] * vander[j, i] for j in range(len(ks))) | |
| for i in range(num_samples)] |
| field = 0 if len(V) == 1 else bc.function_space_index() | ||
| comp = (bc.function_space().component,) | ||
| ws = stages.subfunctions[field::len(V)] | ||
| ws = stages.subfunctions[field :: len(V)] |
There was a problem hiding this comment.
| ws = stages.subfunctions[field :: len(V)] | |
| ws = stages.subfunctions[field::len(V)] |
| return type(self)( | ||
| V, | ||
| g, | ||
| sub_domain, | ||
| self.bounds, | ||
| self.solver_parameters, | ||
| backend=self._backend_name, | ||
| ) |
There was a problem hiding this comment.
| return type(self)( | |
| V, | |
| g, | |
| sub_domain, | |
| self.bounds, | |
| self.solver_parameters, | |
| backend=self._backend_name, | |
| ) | |
| return type(self)(V, g, sub_domain, self.bounds, self.solver_parameters) |
Co-authored-by: Jørgen Schartum Dokken <dokken92@gmail.com>
| problem: dolfinx.fem.petsc.LinearProblem | dolfinx.fem.petsc.NonlinearProblem, | ||
| **kwargs, | ||
| ): | ||
| """Create a linear variational solver that uses PETSc KSP.""" |
There was a problem hiding this comment.
| """Create a linear variational solver that uses PETSc KSP.""" | |
| """Create a variational solver that uses PETSc SNES or KSP.""" |
|
|
||
| from petsc4py import PETSc | ||
| from .tools import AI, getNullspace, flatten_dats, split_stages | ||
| from .labeling import as_form |
There was a problem hiding this comment.
| from .labeling import as_form | |
| try: | |
| from .labeling import as_form | |
| except ImportError: | |
| as_form = lambda x: x |
| self.sample_values = [ | ||
| sum(ks[j] * vander[j, i] for j in range(len(ks))) | ||
| for i in range(num_samples) | ||
| ] |
There was a problem hiding this comment.
| self.sample_values = [ | |
| sum(ks[j] * vander[j, i] for j in range(len(ks))) | |
| for i in range(num_samples) | |
| ] | |
| self.sample_values = [sum(ks[j] * vander[j, i] for j in range(len(ks))) | |
| for i in range(num_samples)] |
Minimal example: